package com.zanfeng.signleplatform.common.utils;

import com.github.dozermapper.core.DozerBeanMapper;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import com.zanfeng.signleplatform.constants.Constants;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2017/4/7.
 */
public class BeanUtil {

    static Logger _logger = LoggerFactory.getLogger(BeanUtil.class);

    public static <T> T entityInit(T entity) {
        return entity;
    }

    private static String loadSetMethodName(String filedName) {
        return "set" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
    }

    private static void invokeMethod(Class<?> entityClass, String methodName, Class<?> paramaterType, Object entity, Object param) {
        try {
            entityClass.getMethod(methodName, paramaterType).invoke(entity, param);
        } catch (Exception e) {
        }
    }


    private static Mapper mapper = DozerBeanMapperBuilder.buildDefault();

    public static <T> T cast(Object source, Class<T> targetClass) {
        T result = mapper.map(source, targetClass);
        return result;
    }

    public static <T> T castInit(Object source, Class<T> targetClass) {
        T result = mapper.map(source, targetClass);
        try {
            setFieldValue(result, "isDelete", Constants.False);
            setFieldValue(result, "isPublish", Constants.True);
            setFieldValue(result, "updateTime", new Date());
            setFieldValue(result, "createTime", new Date());
            setFieldValue(result, "orderNum", 0);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return result;
    }

    private static void setFieldValue(Object object, String fieldName, Object value) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        if (PropertyUtils.isWriteable(object, fieldName)) {
            PropertyUtils.setProperty(object, fieldName, value);
        }
    }

    /**
     * 将一个 JavaBean 对象转化为一个  Map
     *
     * @param bean 要转化的JavaBean 对象
     * @return 转化出来的  Map 对象
     * @throws IntrospectionException    如果分析类属性失败
     * @throws IllegalAccessException    如果实例化 JavaBean 失败
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static Map convertBean(Object bean) {
        Map returnMap = new HashMap();
        try {
            Class type = bean.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(type);

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if (!propertyName.equals("class")) {
                    Method readMethod = descriptor.getReadMethod();
                    Object result = readMethod.invoke(bean, new Object[0]);
                    if (result != null) {
                        returnMap.put(propertyName, result);
                    } else {
                        returnMap.put(propertyName, "");
                    }
                }
            }
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage());
        }
        return returnMap;
    }


    /**
     * 将一个 Map 对象转化为一个 JavaBean
     *
     * @param type 要转化的类型
     * @param map  包含属性值的 map
     * @return 转化出来的 JavaBean 对象
     * @throws IntrospectionException    如果分析类属性失败
     * @throws IllegalAccessException    如果实例化 JavaBean 失败
     * @throws InstantiationException    如果实例化 JavaBean 失败
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败
     */
    @SuppressWarnings("rawtypes")
    public static Object convertMap(Class type, Map map)
            throws IntrospectionException, IllegalAccessException,
            InstantiationException, InvocationTargetException {
        BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
        Object obj = type.newInstance(); // 创建 JavaBean 对象

        // 给 JavaBean 对象的属性赋值
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i < propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();

            if (map.containsKey(propertyName)) {
                // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
                Object value = map.get(propertyName);

                Object[] args = new Object[1];
                args[0] = value;

                descriptor.getWriteMethod().invoke(obj, args);
            }
        }
        return obj;
    }

}
